package com.notice.rule.print;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.notice.config.LogSpringContent;
import com.notice.entity.LogDingProperties;
import com.notice.entity.NoticePrint;
import org.springframework.stereotype.Component;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 重复消息处理
 *
 * @author DZL
 * @date 2023/1/13 14:14
 */
@Component
public class RepeatMsgProcess extends AbstractNoticeMsgProcessHandler {

    /**
     * 缓存队列
     */
    private static final Cache<String, AtomicInteger> FIFO_CACHE;

    /**
     * 重复信息发送的阈值
     */
    private static final Integer THRESHOLD = 5;

    static {
        final Long repeatTime = LogSpringContent.getApplicationContext().getBean(LogDingProperties.class).getRepeatTime();
        FIFO_CACHE = CacheUtil.newLRUCache(100, repeatTime);
    }

    @Override
    int order() {
        return -1;
    }

    @Override
    NoticePrint printProcessing(ILoggingEvent event, NoticePrint noticePrint) {
        //1、信息md5计算,线程安全
        String printMsg = noticePrint.getErrorMsg().concat(noticePrint.getStackMsg());
        String md5 = DigestUtil.md5Hex(printMsg);
        AtomicInteger count = FIFO_CACHE.get(md5, () -> new AtomicInteger(0));
        //2、阈值控制
        if (count.incrementAndGet() % THRESHOLD != 0) {
            if (count.get() == 1) {
                return noticePrint;
            }
            noticePrint = new NoticePrint();
        } else {
            //3、简易信息
            StringBuilder sb = new StringBuilder("堆栈信息：\n\n");
            IThrowableProxy throwableProxy = event.getThrowableProxy();
            if (throwableProxy != null) {
                sb.append(throwableProxy.getClassName()).append(":").append(throwableProxy.getMessage()).append("\n");
            }
            sb.append("指定时间内触发次数：").append(count.get()).append("\n").append("请及时关注......");
            noticePrint.setStackMsg(sb.toString());
        }
        return noticePrint;
    }
}
